package cn.snmp.mutual.uk.stack;

import java.util.*;
import java.io.*;

public class SnmpContextv2c extends SnmpContext implements SnmpContextv2cFace, Cloneable {
    private static final String version_id = "@(#)$Id: SnmpContextv2c.java,v 3.16 2009/03/05 12:54:04 birgita Exp $ Copyright Westhawk Ltd";

    public SnmpContextv2c(final String host, final int port) throws IOException {
        super(host, port);
    }

    public SnmpContextv2c(final String host, final int port, final String typeSocketA) throws IOException {
        super(host, port, typeSocketA);
    }

    public SnmpContextv2c(final String host, final int port, final String bindAddress, final String typeSocketA) throws IOException {
        super(host, port, bindAddress, typeSocketA);
    }

    @Override
    public int getVersion() {
        return 1;
    }

    @Override
    public byte[] encodePacket(final byte msg_type, final int rId, final int errstat, final int errind, final Enumeration ve, final Object obj) throws IOException, EncodingException {
        byte[] packet = null;
        if (this.isDestroyed) {
            throw new EncodingException("Context can no longer be used, since it is already destroyed");
        }
        final AsnEncoderv2c enc = new AsnEncoderv2c();
        final ByteArrayOutputStream bay = enc.EncodeSNMPv2c(this, msg_type, rId, errstat, errind, ve);
        final int sz = bay.size();
        if (sz > this.maxRecvSize) {
            throw new EncodingException("Packet size (" + sz + ") is > maximum size (" + this.maxRecvSize + ")");
        }
        packet = bay.toByteArray();
        return packet;
    }

    @Override
    protected void processIncomingResponse(final ByteArrayInputStream in) throws DecodingException, IOException {
        final AsnDecoderv2c rpdu = new AsnDecoderv2c();
        final AsnPduSequence pduSeq = rpdu.DecodeSNMPv2c(in, this.getCommunity());
        if (pduSeq != null) {
            final Integer rid = new Integer(pduSeq.getReqId());
            final Pdu answ = this.getPdu(rid);
            if (answ != null) {
                answ.fillin(pduSeq);
            } else if (AsnObject.debug > 3) {
                System.out.println(this.getClass().getName() + ".processIncomingResponse(): No Pdu with reqid " + (int) rid);
            }
        } else if (AsnObject.debug > 3) {
            System.out.println(this.getClass().getName() + ".processIncomingResponse(): Error - missing seq input");
        }
    }

    @Override
    public Pdu processIncomingPdu(final byte[] message) throws DecodingException, IOException {
        final AsnDecoderv2c rpdu = new AsnDecoderv2c();
        final ByteArrayInputStream in = new ByteArrayInputStream(message);
        final AsnPduSequence pduSeq = rpdu.DecodeSNMPv2c(in, this.getCommunity());
        Pdu pdu = null;
        if (pduSeq != null) {
            final byte type = pduSeq.getRespType();
            switch (type) {
                case -96: {
                    pdu = new GetPdu(this);
                    break;
                }
                case -95: {
                    pdu = new GetNextPdu(this);
                    break;
                }
                case -93: {
                    pdu = new SetPdu(this);
                    break;
                }
                case -91: {
                    pdu = new GetBulkPdu(this);
                    break;
                }
                case -90: {
                    pdu = new InformPdu(this);
                    break;
                }
                case -89: {
                    pdu = new TrapPduv2(this);
                    break;
                }
                default: {
                    if (AsnObject.debug > 3) {
                        System.out.println(this.getClass().getName() + ".ProcessIncomingPdu(): PDU received with type " + pduSeq.getRespTypeString() + ". Ignoring it.");
                        break;
                    }
                    break;
                }
            }
            if (pdu != null) {
                pdu.fillin(pduSeq);
            }
        }
        return pdu;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        SnmpContextv2c clContext = null;
        try {
            clContext = new SnmpContextv2c(this.hostname, this.hostPort, this.bindAddr, this.typeSocket);
            clContext.setCommunity(new String(this.community));
        } catch (IOException exc) {
            throw new CloneNotSupportedException("IOException " + exc.getMessage());
        }
        return clContext;
    }

    @Override
    public String getHashKey() {
        return super.getHashKey();
    }

    @Override
    public String toString() {
        final StringBuffer buffer = new StringBuffer("SnmpContextv2c[");
        buffer.append("host=").append(this.hostname);
        buffer.append(", port=").append(this.hostPort);
        buffer.append(", bindAddress=").append(this.bindAddr);
        buffer.append(", socketType=").append(this.typeSocket);
        buffer.append(", community=").append(this.community);
        buffer.append(", #trapListeners=").append(this.trapSupport.getListenerCount());
        buffer.append(", #pduListeners=").append(this.pduSupport.getListenerCount());
        buffer.append("]");
        return buffer.toString();
    }
}
